home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / net_bw.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  19KB  |  764 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // net_bw.c
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <dpmi.h>
  25.  
  26. #include "quakedef.h"
  27. #include "dosisms.h"
  28.  
  29.  
  30. // this section is general Unix stuff that we need
  31.  
  32. #define    EIO                 5    /* I/O error */
  33. #define EBADS            9
  34. #define EWOULDBLOCK        35    /* function would block */
  35. #define EMSGSIZE        40    /* message to big for buffers */
  36. #define    EPROTONOSUPPORT    43    /* Protocol not supported */
  37. #define    ESOCKTNOSUPPORT    44    /* Socket type not supported */
  38. #define    EPFNOSUPPORT    46    /* Protocol family not supported */
  39. #define EAFNOSUPPORT    47    /* Address family not supported */
  40. #define ECONNABORTED    53    /* User requested hangup */
  41. #define ENOBUFS         55    /* No buffers available */
  42. #define EISCONN         56    /* Socket has closed */
  43. #define ENOTCONN        57    /* Socket is not connected */
  44. #define ESHUTDOWN        58    /* Socket is closed */
  45. #define ETOOMANYREFS    59    /* Too many sockets open */
  46. #define ETIMEDOUT        60    /* Connection timed out */
  47. #define ECONNREFUSED    61    /* Connection refused */
  48.  
  49. #define AF_INET         2    /* internet */
  50.  
  51. #define PF_INET            AF_INET
  52.  
  53. #define SOCK_STREAM        1        /* stream */
  54. #define SOCK_DGRAM        2        /* datagram */
  55.  
  56. #define IPPROTO_TCP        6
  57. #define IPPROTO_UDP        17
  58.  
  59. #define INADDR_ANY        0
  60.  
  61. #define SIOCDONE        0x7300
  62. #define FIONREAD        0x667f
  63. #define FIONBIO         0x667e
  64. #define FIONWIN         0x1000
  65. #define FIONTIN         0x2000
  66.  
  67. #define BRDINIT         0
  68. #define BRDADDR         10
  69.  
  70. #define MAXHOSTNAMELEN    256
  71.  
  72. #define SOL_SOCKET        0xffff        /* options for socket level */
  73.  
  74. /*
  75.  * Option flags per-socket.
  76.  */
  77. #define SO_DEBUG        0x0001        /* turn on debugging info recording */
  78. #define SO_ACCEPTCONN    0x0002        /* socket has had listen() */
  79. #define SO_REUSEADDR    0x0004        /* allow local address reuse */
  80. #define SO_KEEPALIVE    0x0008        /* keep connections alive */
  81. #define SO_DONTROUTE    0x0010        /* just use interface addresses */
  82. #define SO_BROADCAST    0x0020        /* permit sending of broadcast msgs */
  83. #define SO_USELOOPBACK    0x0040        /* bypass hardware when possible */
  84. #define SO_LINGER        0x0080        /* linger on close if data present */
  85. #define SO_OOBINLINE    0x0100        /* leave received OOB data in line */
  86. #define SO_USEPRIV        0x4000        /* allocate from privileged port area */
  87. #define SO_CANTSIG        0x8000        /* prevent SIGPIPE on SS_CANTSENDMORE */
  88.  
  89. /*
  90.  * Additional options, not kept in so_options.
  91.  */
  92. #define SO_SNDBUF        0x1001        /* send buffer size */
  93. #define SO_RCVBUF        0x1002        /* receive buffer size */
  94. #define SO_SNDLOWAT        0x1003        /* send low-water mark */
  95. #define SO_RCVLOWAT        0x1004        /* receive low-water mark */
  96. #define SO_SNDTIMEO        0x1005        /* send timeout */
  97. #define SO_RCVTIMEO        0x1006        /* receive timeout */
  98. #define SO_ERROR        0x1007        /* get error status and clear */
  99. #define SO_TYPE            0x1008        /* get socket type */
  100.  
  101.  
  102. struct in_addr
  103. {
  104.     union
  105.     {
  106.         struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
  107.         struct { unsigned short s_w1,s_w2; } S_un_w;
  108.         unsigned long S_addr;
  109.     } S_un;
  110. };
  111. #define    s_addr    S_un.S_addr    /* can be used for most tcp & ip code */
  112. #define    s_host    S_un.S_un_b.s_b2    /* host on imp */
  113. #define    s_net    S_un.S_un_b.s_b1    /* network */
  114. #define    s_imp    S_un.S_un_w.s_w2    /* imp */
  115. #define    s_impno    S_un.S_un_b.s_b4    /* imp # */
  116. #define    s_lh    S_un.S_un_b.s_b3    /* logical host */
  117.  
  118. struct sockaddr_in
  119. {
  120.     short            sin_family;
  121.     unsigned short    sin_port;
  122.     struct in_addr    sin_addr;
  123.     char            sin_zero[8];
  124. };
  125.  
  126. struct    hostent {
  127.     char    *h_name;    /* official name of host */
  128.     char    **h_aliases;    /* alias list */
  129.     int    h_addrtype;    /* host address type */
  130.     int    h_length;    /* length of address */
  131.     char    **h_addr_list;    /* list of addresses from name server */
  132. #define    h_addr    h_addr_list[0]    /* address, for backward compatiblity */
  133. };
  134.  
  135. char *inet_ntoa(struct in_addr in);
  136.  
  137.  
  138. // this section is B&W specific constants & structures
  139.  
  140. #define BW_IOCTL_BIND            0
  141. #define BW_IOCTL_CLEAROPTIONS    5
  142. #define BW_IOCTL_SETOPTIONS        6
  143. #define BW_IOCTL_PEEK            7
  144. #define BW_IOCTL_SETWINMASK        8
  145.  
  146. #define BW_OPTION_BLOCKING        0x01
  147. #define BW_OPTION_REUSEBUFFERS    0x80
  148.  
  149. #define BW_ERR_USR_HANGUP        50
  150. #define BW_ERR_HANGUP            51
  151. #define BW_ERR_NET_ERR            52
  152. #define BW_ERR_IS_CLOSED        53
  153. #define BW_ERR_TIME_OUT            54
  154. #define BW_ERR_RESET            55
  155. #define BW_ERR_FULL                56
  156. #define BW_ERR_BLOCK            57
  157. #define BW_ERR_SHUTDOWN            58
  158.  
  159. #pragma pack(1)
  160.  
  161. typedef struct
  162. {
  163.     char            state;            // always 1
  164.     short            localPort;
  165.     struct in_addr    localAddr;
  166.     char            reason;            // always 0
  167.     char            options;
  168.     short            dataAvailable;
  169. } BW_UDPinfo_t;
  170.  
  171. typedef struct
  172. {
  173.     char            reserved1 [6];
  174.     unsigned short    info2Offset;
  175.     char            reserved2 [18];
  176.     struct in_addr    remoteAddr;
  177. } BW_UDPreadInfo1_t;
  178.  
  179. typedef struct
  180. {
  181.     short            remotePort;
  182.     char            reserved1 [2];
  183.     unsigned short    dataLenPlus8;
  184.     char            reserved2 [2];
  185.     char            data[1];            // actual size is <dataLenPlus8> - 8        
  186. } BW_UDPreadInfo2_t;
  187.  
  188. typedef struct
  189. {
  190.     char            reserved1 [2];
  191.     short            remotePort;
  192.     unsigned short    dataLen;
  193.     struct in_addr    remoteAddr;
  194.     char            reserved2 [42];
  195.     char            data[1];            // actual size is <datalen>
  196. } BW_writeInfo_t;
  197.  
  198. typedef struct
  199. {
  200.     short    ioport;
  201.     byte    dma;
  202.     byte    vector;
  203.     byte    irq;
  204.     short    bufferSize;
  205.     short    maxWindow;
  206.     short    timeZone;
  207.     byte    myType;
  208.     int        inetAddr;
  209.     short    value;
  210.     byte    subnetMask;
  211.     short    etherPointer;
  212.     short    logserverPointer;
  213.     short    nameserverPointer;
  214.     short    printserverPointer;
  215.     short    timeserverPointer;
  216.     short    gatewayPointer;
  217.     short    driverSegment;
  218.     byte    transferSize;
  219.     char    cardName [9];
  220. } BW_ethdevinfo_t;
  221.  
  222. #pragma pack()
  223.  
  224. #define LOWMEM_SIZE    4096
  225.  
  226. static unsigned char *lowmem_buffer;
  227. static int lowmem_bufseg;
  228. static int lowmem_bufoff;
  229. static BW_ethdevinfo_t ethdevinfo;
  230. static int netmask;
  231. static struct in_addr bcastaddr;
  232.  
  233. extern regs_t regs;
  234.  
  235. static int net_acceptsocket = -1;        // socket for fielding new connections
  236. static int net_controlsocket = 0;
  237.  
  238. #include "net_bw.h"
  239.  
  240. //=============================================================================
  241.  
  242. static int BW_ioctl(int s, char *msg, int msglen)
  243. {
  244.     Q_memcpy(lowmem_buffer, msg, msglen);
  245.  
  246.     regs.x.ax = 0x4403;
  247.     regs.x.bx = s;
  248.     regs.x.cx = msglen;
  249.     regs.x.dx = lowmem_bufoff;
  250.     regs.x.ds = lowmem_bufseg;
  251.     if (dos_int86(0x21))
  252.         return regs.x.ax;
  253.     return 0;
  254. }
  255.  
  256. //=============================================================================
  257.  
  258. static int BW_TranslateError(int error)
  259. {
  260.     switch(error)
  261.     {
  262.         case BW_ERR_USR_HANGUP:    return ECONNABORTED;
  263.         case BW_ERR_HANGUP:        return EISCONN;
  264.         case BW_ERR_NET_ERR:    return ENOTCONN;
  265.         case BW_ERR_IS_CLOSED:    return ENOTCONN;
  266.         case BW_ERR_TIME_OUT:    return ETIMEDOUT;
  267.         case BW_ERR_RESET:        return ECONNREFUSED;
  268.         case BW_ERR_FULL:        return ETOOMANYREFS;
  269.         case BW_ERR_BLOCK:        return EWOULDBLOCK;
  270.         case BW_ERR_SHUTDOWN:    return ESHUTDOWN;
  271.     }
  272.     return EIO;
  273. }
  274.  
  275. //=============================================================================
  276.  
  277. static int GetEthdevinfo(void)
  278. {
  279.     int fd;
  280.  
  281.     Q_strcpy((char *)lowmem_buffer, "ETHDEV27");
  282.     regs.x.ax = 0x3d42;
  283.     regs.x.ds = lowmem_bufseg;
  284.     regs.x.dx = lowmem_bufoff;
  285.     if (dos_int86(0x21))
  286.         return -1;
  287.     fd = regs.x.ax;
  288.  
  289.     regs.x.ax = 0x4401;
  290.     regs.x.bx = fd;
  291.     regs.x.dx = 0x60;
  292.     dos_int86(0x21);
  293.  
  294.     regs.h.ah = 0x3f;
  295.     regs.x.cx = sizeof(ethdevinfo);
  296.     regs.x.es = regs.x.ds = lowmem_bufseg;
  297.     regs.x.dx = lowmem_bufoff;
  298.     regs.x.bx = fd;
  299.     if (dos_int86(0x21))
  300.         return -1;
  301.     Q_memcpy(ðdevinfo, lowmem_buffer, regs.x.ax);
  302.  
  303.     regs.h.ah = 0x3e;
  304.     regs.x.bx = fd;
  305.     dos_int86(0x21);
  306.  
  307.     return 0;
  308. }
  309.  
  310. //=============================================================================
  311.  
  312. int BW_Init(void)
  313. {
  314.     struct qsockaddr addr;
  315.     char *colon;
  316.  
  317.     if (COM_CheckParm ("-noudp"))
  318.         return -1;
  319.  
  320.     lowmem_buffer = dos_getmemory(LOWMEM_SIZE);
  321.     if (!lowmem_buffer)
  322.         Sys_Error("not enough low memory\n");
  323.     lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
  324.     lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
  325.  
  326.     if (GetEthdevinfo())
  327.     {
  328.         Con_DPrintf("Beame & Whiteside TCP/IP not detected\n");
  329.         dos_freememory(lowmem_buffer);
  330.         return -1;
  331.     }
  332.     netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask);
  333.     bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask);
  334.  
  335.     if ((net_controlsocket = BW_OpenSocket (0)) == -1)
  336.     {
  337.         dos_freememory(lowmem_buffer);
  338.         Con_DPrintf ("BW_Init unable to open control socket; disabled\n");
  339.         return -1;
  340.     }
  341.  
  342.     BW_GetSocketAddr (net_controlsocket, &addr);
  343.     Q_strcpy(my_tcpip_address,  BW_AddrToString (&addr));
  344.     colon = Q_strrchr (my_tcpip_address, ':');
  345.     if (colon)
  346.         *colon = 0;
  347.  
  348.     Con_Printf("BW_Init: UDP initialized\n");
  349.     tcpipAvailable = true;
  350.  
  351.     return net_controlsocket;
  352. }
  353.  
  354. //=============================================================================
  355.  
  356. void BW_Shutdown(void)
  357. {
  358.     BW_Listen (false);
  359.     BW_CloseSocket (net_controlsocket);
  360.     dos_freememory(lowmem_buffer);
  361. }
  362.  
  363. //=============================================================================
  364.  
  365. void BW_Listen (qboolean state)
  366. {
  367.     // enable listening
  368.     if (state)
  369.     {
  370.         if (net_acceptsocket != -1)
  371.             return;
  372.         if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1)
  373.             Sys_Error ("BW_Listen: Unable to open accept socket\n");
  374.         return;
  375.     }
  376.  
  377.     // disable listening
  378.     if (net_acceptsocket == -1)
  379.         return;
  380.     BW_CloseSocket (net_acceptsocket);
  381.     net_acceptsocket = -1;
  382. }
  383.  
  384.  
  385. //=============================================================================
  386.  
  387. /*
  388. OpenSocket returns a handle to a network socket that has been opened,
  389. set to nonblocking, and bound to <port>.  Additional socket options
  390. should be set here if they are needed.  -1 is returned on failure.
  391. */
  392.  
  393. int BW_OpenSocket(int port)
  394. {
  395.     int s;
  396.     int ret;
  397.     int deadman = 3 * 1024;
  398.     static int dynamic = 1024;
  399.     static char reuse_msg[2] = {BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS};
  400.     static char bind_msg[3] = {BW_IOCTL_BIND, 0, 0};
  401.     static char nonblock_msg[2] = {BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING};
  402.  
  403.     // allocate a UDP socket
  404.     Q_strcpy((char *)lowmem_buffer, "UDP-IP10");
  405.     regs.x.ax = 0x3d42;
  406.     regs.x.ds = lowmem_bufseg;
  407.     regs.x.dx = lowmem_bufoff;
  408.     if (dos_int86(0x21))
  409.     {
  410.         Con_Printf("BW_OpenSocket failed: %u\n", BW_TranslateError(regs.x.ax));
  411.         return -1;
  412.     }
  413.     s = regs.x.ax;
  414.  
  415.     // set file descriptor to raw mode
  416.     regs.x.ax = 0x4401;
  417.     regs.x.bx = s;
  418.     regs.x.dx = 0x60;
  419.     dos_int86(0x21);
  420.  
  421.     if (BW_ioctl(s, reuse_msg, 2))
  422.     {
  423.         Con_Printf("BW_OpenSocket ioctl(reuse) failed\n");
  424.         return -1;
  425.     }
  426.  
  427.     if (BW_ioctl(s, nonblock_msg, 2))
  428.     {
  429.         Con_Printf("BW_OpenSocket ioctl(nonblocking) failed\n");
  430.         return -1;
  431.     }
  432.  
  433.     // if a socket was specified, bind to it and return
  434.     if (port)
  435.     {
  436.         *(short *)&bind_msg[1] = port;
  437.         if (BW_ioctl(s, bind_msg, 3))
  438.         {
  439.             BW_CloseSocket(s);
  440.             return -1;
  441.         }
  442.         return s;
  443.     }
  444.  
  445.     // B&W does NOT do dynamic allocation, so if port == 0 we must fake it
  446.     do
  447.     {
  448.         port = dynamic++;
  449.         if (dynamic == 4096)
  450.             dynamic = 1024;
  451.         deadman--;
  452.         *(short *)&bind_msg[1] = port;
  453.         ret = BW_ioctl(s, bind_msg, 3);
  454.     }
  455.     while (ret && deadman);
  456.     if (ret)
  457.         return -1;
  458.     return s;
  459. }
  460.  
  461. //=============================================================================
  462.  
  463. int BW_CloseSocket(int socket)
  464. {
  465.     regs.h.ah = 0x3e;
  466.     regs.x.bx = socket;
  467.     if(dos_int86(0x21))
  468.         {
  469.             Con_Printf("BW_CloseSocket %u failed: %u\n", socket, BW_TranslateError(regs.x.ax));
  470.             return -1;
  471.         }
  472.     return 0;
  473. }
  474.  
  475. //=============================================================================
  476.  
  477. int BW_Connect (int socket, struct qsockaddr *hostaddr)
  478. {
  479.     return 0;
  480. }
  481.  
  482. //=============================================================================
  483.  
  484. int BW_CheckNewConnections(void)
  485. {
  486.     if (net_acceptsocket == 0)
  487.         return -1;
  488.  
  489.     // see if there's anything waiting
  490.     regs.x.ax = 0x4406;
  491.     regs.x.bx = net_acceptsocket;
  492.     dos_int86(0x21);
  493.     if (regs.x.ax == 0)
  494.         return -1;
  495.     return net_acceptsocket;
  496. }
  497.  
  498. //=============================================================================
  499.  
  500. int BW_Read(int s, byte *buf, int len, struct qsockaddr *from)
  501. {
  502.     BW_UDPreadInfo1_t *info1;
  503.     BW_UDPreadInfo2_t *info2;
  504.  
  505.     // ask if there's anything waiting
  506.     regs.x.ax = 0x4406;
  507.     regs.x.bx = s;
  508.     dos_int86(0x21);
  509.     if (regs.x.ax == 0)
  510.         return 0;
  511.  
  512.     // there was, so let's get it
  513.     regs.h.ah = 0x3f;
  514.     regs.x.cx = /* len + 53 */ LOWMEM_SIZE;
  515.     regs.x.es = regs.x.ds = lowmem_bufseg;
  516.     regs.x.dx = lowmem_bufoff;
  517.     regs.x.bx = s;
  518.     if (dos_int86(0x21))
  519.     {
  520.         Con_Printf("BW UDP read error: %u\n", BW_TranslateError(regs.x.ax));
  521.         return -1;
  522.     }
  523.  
  524.     info1 = (BW_UDPreadInfo1_t *)lowmem_buffer;
  525.     info2 = (BW_UDPreadInfo2_t *)(lowmem_buffer + info1->info2Offset);
  526.  
  527.     if (from)
  528.     {
  529.         from->sa_family = AF_INET;
  530.         ((struct sockaddr_in *)from)->sin_addr = info1->remoteAddr;
  531.         ((struct sockaddr_in *)from)->sin_port = htons(info2->remotePort);
  532.     }
  533.  
  534.     len = info2->dataLenPlus8 - 8;
  535.     if (len > NET_DATAGRAMSIZE)
  536.     {
  537.         Con_Printf("BW UDP read packet too large: %u\n", len);
  538.         return -1;
  539.     }
  540.     Q_memcpy(buf, info2->data, len);
  541.  
  542.     return len;
  543. }
  544.  
  545. //=============================================================================
  546.  
  547. int BW_Broadcast(int s, byte *msg, int len)
  548. {
  549.     BW_writeInfo_t *writeInfo;
  550.  
  551.     // ask if we're clear to send
  552.     regs.x.ax = 0x4407;
  553.     regs.x.bx = s;
  554.     dos_int86(0x21);
  555.     if (regs.x.ax == 0)
  556.         return 0;
  557.  
  558.     // yes, let's do it
  559.     writeInfo = (BW_writeInfo_t *)lowmem_buffer;
  560.     writeInfo->remoteAddr = bcastaddr;
  561.     writeInfo->remotePort = net_hostport;
  562.     writeInfo->dataLen = len;
  563.     if (len > NET_DATAGRAMSIZE)
  564.         Sys_Error("BW UDP write packet too large: %u\n", len);
  565.     Q_memcpy(writeInfo->data, msg, len);
  566.     writeInfo->data[len] = 0;
  567.     regs.h.ah = 0x40;
  568.     regs.x.bx = s;
  569.     regs.x.cx = len + sizeof(BW_writeInfo_t);
  570.     regs.x.es = regs.x.ds = lowmem_bufseg;
  571.     regs.x.dx = lowmem_bufoff;
  572.     if (dos_int86(0x21))
  573.     {
  574.         Con_Printf("BW_Broadcast failed: %u\n", BW_TranslateError(regs.x.ax));
  575.         return -1;
  576.     }
  577.  
  578.     return len;
  579. }
  580.  
  581. //=============================================================================
  582.  
  583. int BW_Write(int s, byte *msg, int len, struct qsockaddr *to)
  584. {
  585.     BW_writeInfo_t *writeInfo;
  586.  
  587.     // ask if we're clear to send
  588.     regs.x.ax = 0x4407;
  589.     regs.x.bx = s;
  590.     dos_int86(0x21);
  591.     if (regs.x.ax == 0)
  592.         return 0;
  593.  
  594.     // yes, let's do it
  595.     writeInfo = (BW_writeInfo_t *)lowmem_buffer;
  596.     writeInfo->remoteAddr = ((struct sockaddr_in *)to)->sin_addr;
  597.     writeInfo->remotePort = ntohs(((struct sockaddr_in *)to)->sin_port);
  598.     writeInfo->dataLen = len;
  599.     if (len > NET_DATAGRAMSIZE)
  600.         Sys_Error("BW UDP write packet too large: %u\n", len);
  601.     Q_memcpy(writeInfo->data, msg, len);
  602.     writeInfo->data[len] = 0;
  603.     regs.h.ah = 0x40;
  604.     regs.x.bx = s;
  605.     regs.x.cx = len + sizeof(BW_writeInfo_t);
  606.     regs.x.es = regs.x.ds = lowmem_bufseg;
  607.     regs.x.dx = lowmem_bufoff;
  608.     if (dos_int86(0x21))
  609.     {
  610.         Con_Printf("BW_Write failed: %u\n", BW_TranslateError(regs.x.ax));
  611.         return -1;
  612.     }
  613.  
  614.     return len;
  615. }
  616.  
  617. //=============================================================================
  618.  
  619.  
  620. char *BW_AddrToString (struct qsockaddr *addr)
  621. {
  622.     static char buffer[22];
  623.  
  624.     sprintf(buffer, "%d.%d.%d.%d:%d",
  625.         ((struct sockaddr_in *)addr)->sin_addr.s_net,
  626.         ((struct sockaddr_in *)addr)->sin_addr.s_host,
  627.         ((struct sockaddr_in *)addr)->sin_addr.s_lh,
  628.         ((struct sockaddr_in *)addr)->sin_addr.s_impno,
  629.         ntohs(((struct sockaddr_in *)addr)->sin_port)
  630.         );
  631.     return buffer;
  632. }
  633.  
  634. //=============================================================================
  635.  
  636. int BW_StringToAddr (char *string, struct qsockaddr *addr)
  637. {
  638.     int ha1, ha2, ha3, ha4, hp;
  639.     int ipaddr;
  640.  
  641.     sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  642.     ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  643.  
  644.     addr->sa_family = AF_INET;
  645.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  646.     ((struct sockaddr_in *)addr)->sin_port = htons((short)hp);
  647.     return 0;
  648. }
  649.  
  650. //=============================================================================
  651.  
  652. int BW_GetSocketAddr (int socket, struct qsockaddr *addr)
  653. {
  654.     regs.x.ax = 0x4402;
  655.     regs.x.bx = socket;
  656.     regs.x.cx = sizeof(BW_UDPinfo_t);
  657.     regs.x.dx = lowmem_bufoff;
  658.     regs.x.ds = lowmem_bufseg;
  659.     dos_int86(0x21);
  660.  
  661.     addr->sa_family = AF_INET;
  662.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = ((BW_UDPinfo_t *)lowmem_buffer)->localAddr.s_addr;
  663.     ((struct sockaddr_in *)addr)->sin_port = htons(((BW_UDPinfo_t *)lowmem_buffer)->localPort);
  664.  
  665.     return 0;
  666. }
  667.  
  668. //=============================================================================
  669.  
  670. int BW_GetNameFromAddr (struct qsockaddr *addr, char *name)
  671. {
  672.     Q_strcpy(name, BW_AddrToString(addr));
  673.     return 0;
  674. }
  675.  
  676. ///=============================================================================
  677.  
  678. int BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr)
  679. {
  680.     char buff[MAXHOSTNAMELEN];
  681.     char *b;
  682.     int addr;
  683.     int num;
  684.     int mask;
  685.     int run;
  686.     int port;
  687.  
  688.     if (name[0] < '0' || name[0] > '9')
  689.         return -1;
  690.  
  691.     buff[0] = '.';
  692.     b = buff;
  693.     Q_strcpy(buff+1, name);
  694.     if (buff[1] == '.')
  695.         b++;
  696.  
  697.     addr = 0;
  698.     mask = -1;
  699.     while (*b == '.')
  700.     {
  701.         b++;
  702.         num = 0;
  703.         run = 0;
  704.         while (!( *b < '0' || *b > '9'))
  705.         {
  706.           num = num*10 + *b++ - '0';
  707.           if (++run > 3)
  708.               return -1;
  709.         }
  710.         if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  711.             return -1;
  712.         if (num < 0 || num > 255)
  713.             return -1;
  714.         mask<<=8;
  715.         addr = (addr<<8) + num;
  716.     }
  717.     addr = htonl(addr);
  718.     mask = htonl(mask);
  719.  
  720.     if (*b++ == ':')
  721.         port = Q_atoi(b);
  722.     else
  723.         port = net_hostport;
  724.  
  725.     hostaddr->sa_family = AF_INET;
  726.     ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);    
  727.     ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr =
  728.     ((ethdevinfo.inetAddr & mask) | addr);
  729.  
  730.     return 0;
  731. }
  732.  
  733. //=============================================================================
  734.  
  735. int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  736. {
  737.     if (addr1->sa_family != addr2->sa_family)
  738.         return -1;
  739.  
  740.     if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  741.         return -1;
  742.  
  743.     if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
  744.         return 1;
  745.  
  746.     return 0;
  747. }
  748.  
  749. //=============================================================================
  750.  
  751. int BW_GetSocketPort (struct qsockaddr *addr)
  752. {
  753.     return ntohs(((struct sockaddr_in *)addr)->sin_port);
  754. }
  755.  
  756.  
  757. int BW_SetSocketPort (struct qsockaddr *addr, int port)
  758. {
  759.     ((struct sockaddr_in *)addr)->sin_port = htons(port);
  760.     return 0;
  761. }
  762.  
  763. //=============================================================================
  764.